home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / VOL_400 / 453_01 / EXAMPLES / STRUCT / STRUCT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-27  |  7.3 KB  |  350 lines

  1. //    struct.cpp  -  data structure display application sample code  -  1.2
  2. //
  3. //    This is a part of the MetaKit library.
  4. //    Copyright (c) 1996 Meta Four Software.
  5. //    All rights reserved.
  6. /////////////////////////////////////////////////////////////////////////////
  7. //
  8. //    This command-line utility displays the data structure of a datafile
  9. //    created with the MetaKit library: as a one-line description (-d), as
  10. //    a terse description without property names (-t), as a graph tree of
  11. //    columns (-c, advanced option), or as a graph tree of fields (default).
  12. //
  13. /////////////////////////////////////////////////////////////////////////////
  14.  
  15. #include "m4kit.h"
  16. #include "k4field.h"
  17. #include "k4table.h"
  18.  
  19. /////////////////////////////////////////////////////////////////////////////
  20. // This class generates a string with a pretty tree structure map.
  21.  
  22. class CStructureMap
  23. {
  24. public:
  25.     CStructureMap ();
  26.     
  27.     bool AddNode(int level_, const char* name_,
  28.                     int first_ =0, int count_ =0, char enhance_ =0);
  29.     
  30.     const CString& Result() const    { return _result; }
  31.     
  32. private:
  33.     CWordArray _nextVec;
  34.     CWordArray _limitVec;
  35.     CString _result;
  36. };
  37.  
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CStructureMap
  40.  
  41. CStructureMap::CStructureMap ()
  42. {
  43. }
  44.  
  45.     //@todo does not yet work if repeating/compound field has depth > 0
  46.     
  47. bool CStructureMap::AddNode(int level_, const char* name_,
  48.                                 int first_, int count_, char enhance_)
  49. {
  50.     int n = _nextVec.GetSize();
  51.     if (level_ >= n)
  52.     {
  53.         _nextVec.SetAtGrow(level_, (WORD) first_);
  54.         _limitVec.SetAtGrow(level_, (WORD) (first_ + count_));
  55.         n = level_ + 1;
  56.     }
  57.         
  58.     CString s, t;
  59.  
  60.     for (int i = 0; i < n; ++i)
  61.     {
  62.         bool more = _nextVec[i] < _limitVec[i];
  63.  
  64.         if (i < n - 1 || (more && (int) _nextVec[i] > first_))
  65.         {
  66.             if (i == level_ - 1)
  67.             {
  68.                 int v = (int) _nextVec[i]++;
  69.                     // this uses a silly int to string conversion ...
  70.                 s += CString (v < 10 ? ' ' : '0' + v / 10)
  71.                     + CString ('0' + v % 10) + "+-";
  72.             }
  73.             else
  74.                 s += i < level_ - 1 ? more ? "  | " : "    "
  75.                                     : more ? "--|-" : "----";
  76.         }
  77.         
  78.         t += _nextVec[i] < _limitVec[i] ? "  | " : "    ";
  79.     } 
  80.     
  81.     _result += ((s + " ") + name_) + "\n";
  82.     
  83.     if (enhance_)
  84.     {
  85.         s = t.Left(t.GetLength() - 4) + " ";
  86.         
  87.         int i = strlen(name_);
  88.         if (i < 2)
  89.             i = 2;      
  90.             
  91.         while (--i >= 0)
  92.             s += enhance_;
  93.             
  94.         _result += s + "\n";    
  95.     }
  96.     
  97.     _result += t + "\n";
  98.     
  99.     while (n > 0 && _nextVec[n-1] >= _limitVec[n-1])
  100.         --n;
  101.  
  102.     _nextVec.SetSize(n);
  103.     _limitVec.SetSize(n);
  104.     
  105.     return n > 0;
  106. }                                      
  107.  
  108. /////////////////////////////////////////////////////////////////////////////
  109.  
  110. CString DisplayFieldStructure(const c4_Field& field_)
  111. {
  112.     CStructureMap map;
  113.     
  114.     const c4_Field* f = &field_;
  115.     do
  116.     {
  117.         if (f->NumSubFields() > 0)
  118.         {
  119.             if (f->IsRepeating())
  120.             {
  121.                 map.AddNode(f->Level(), f->Name(), 1, f->NumSubFields() - 1, '=');
  122.                 
  123.                 if (f->NumSubFields() > 1)
  124.                 {
  125.                     f = & f->SubField(1);
  126.                     continue;
  127.                 }
  128.             }
  129.             else
  130.             {
  131.                 map.AddNode(f->Level(), f->Name(), 0, f->NumSubFields(), '-');
  132.                 
  133.                 f = & f->SubField(0);
  134.                 continue;
  135.             }
  136.         }
  137.         else
  138.             map.AddNode(f->Level(), f->Name());
  139.  
  140.         while (!f->IsRoot())
  141.         {
  142.             c4_Field& parent = f->Parent();
  143.                 
  144.             if (f->Index() < parent.NumSubFields() - 1)
  145.             {
  146.                 f = & parent.SubField(f->Index() + 1);
  147.                 break;
  148.             }
  149.                 
  150.             f = & parent;
  151.         }
  152.         
  153.     } while (!f->IsRoot());
  154.     
  155.     return map.Result();
  156. }
  157.  
  158. CString DisplayTableStructure(const c4_Field& field_)
  159. {
  160.     CStructureMap map;
  161.     
  162.     const c4_Field* f = &field_;
  163.     do
  164.     {
  165.         if (f->NumSubFields() > 0)
  166.         {
  167.             if (f->IsRepeating())
  168.             {
  169.                 map.AddNode(f->SubField(0).Degree(), f->Name(),
  170.                                          0, f->NumSubColumns(), '=');
  171.                 if (f->NumSubFields() > 1)
  172.                 {
  173.                     f = & f->SubField(1);
  174.                     continue;
  175.                 }
  176.             }
  177.             else
  178.             {
  179.                 f = & f->SubField(0);
  180.                 continue;
  181.             }
  182.         }
  183.         else if (f->Width() > 0)
  184.             map.AddNode(f->Degree(), f->Name());
  185.  
  186.         while (!f->IsRoot())
  187.         {
  188.             c4_Field& parent = f->Parent();
  189.                 
  190.             if (f->Index() < parent.NumSubFields() - 1)
  191.             {
  192.                 f = & parent.SubField(f->Index() + 1);
  193.                 break;
  194.             }
  195.                 
  196.             f = & parent;
  197.         }
  198.         
  199.     } while (!f->IsRoot());
  200.     
  201.     return map.Result();
  202. }
  203.  
  204. /////////////////////////////////////////////////////////////////////////////
  205.  
  206. #ifdef _DEBUG
  207.  
  208. void TestStructureMap()
  209. {
  210.     static struct c_Info { int level, count; const char* name; } info [] =
  211.     {
  212.         0,  1, "root",
  213.         1,  6, "doc",
  214.         2,  3, "naw",
  215.         3,  2, "n",
  216.         4, -1, "vn",
  217.         2, -1, "x",
  218.         4, -1, "an",
  219.         3, -1, "a",
  220.         3, -1, "w",
  221.         2,  2, "tel",
  222.         3, -1, "n",
  223.         3, -1, "t",
  224.         2,  2, "structure",
  225.         3, -1, "a",
  226.         3, -1, "b",
  227.         2,  0, "aux",
  228.         2,  1, "extra",
  229.         3, -1, "hot",
  230.         0,  0, 0
  231.     };
  232.     
  233.     c4_StructureMap map;
  234.     
  235.     for (c_Info* p = info; p->name; ++p)
  236.         if (p->count >= 0)
  237.             map.AddNode(p->level, p->name, 1, p->count, '=');
  238.         else
  239.             map.AddNode(p->level, p->name);
  240.             
  241.     puts(map.Result());
  242. }
  243.  
  244. /* Output should be:
  245.  
  246.  root 
  247.  ==== 
  248.   |  
  249.  1+- doc 
  250.      === 
  251.       |  
  252.      1+- naw 
  253.       |  === 
  254.       |   |  
  255.       |  1+- n 
  256.       |   |  == 
  257.       |   |   |  
  258.       |   |  1+- vn 
  259.       |   |   |      
  260.      2+---|---|- x 
  261.       |   |   |  
  262.       |   |  2+- an 
  263.       |   |          
  264.       |  2+- a 
  265.       |   |      
  266.       |  3+- w 
  267.       |          
  268.      3+- tel 
  269.       |  === 
  270.       |   |  
  271.       |  1+- n 
  272.       |   |      
  273.       |  2+- t 
  274.       |          
  275.      4+- structure 
  276.       |  ========= 
  277.       |   |  
  278.       |  1+- a 
  279.       |   |      
  280.       |  2+- b 
  281.       |          
  282.      5+- aux 
  283.       |  === 
  284.       |      
  285.      6+- extra 
  286.          ===== 
  287.           |  
  288.          1+- hot
  289. */
  290.  
  291. #endif
  292.  
  293. /////////////////////////////////////////////////////////////////////////////
  294.     
  295. /*! 960228: doesn't work, linker complains about mult-def, even with /NOE ???
  296.         // this stub prevents loading all handlers, which are not needed here
  297.     c4_Handler* f4_CreateHandler(char)
  298.     {
  299.         return 0;
  300.     }            
  301. */
  302.  
  303. int main(int argc, char** argv)
  304. {
  305.     char option = 0;
  306.  
  307.         // check for a leading option and take it off    
  308.     if (argc > 1 && (*argv[1] == '-' || *argv[1] == '/'))
  309.     {
  310.         option = argv[1][1];
  311.         --argc;
  312.         ++argv;
  313.     }
  314.     
  315.         // the debug version tests CStructureMap if no filename is specified
  316.     if (argc != 2)
  317.     {
  318.         #ifdef _DEBUG
  319.             TestStructureMap();
  320.         #else
  321.             fputs("Usage: STRUCT [-d|-t|-c] datafile", stderr);
  322.         #endif
  323.         
  324.         return 1;
  325.     }
  326.  
  327.         // open the file ourselves, so we can use read-only access for it    
  328.     CFile datafile (argv[1], CFile::modeRead);
  329.  
  330.         // open the storage to obtain its structure definition
  331.     c4_Storage store (&datafile);
  332.     c4_Field& def = store.RootTable().Definition();
  333.  
  334.         // display the field structure in one of several formats
  335.     CString s;
  336.     switch (option)
  337.     {
  338.         case 'd': case 'D':        s = def.Description();            break;
  339.         case 't': case 'T':        s = def.Description(true);        break;
  340.         case 'c': case 'C':     s = DisplayTableStructure(def);    break;
  341.         default:                s = DisplayFieldStructure(def);
  342.     }
  343.     puts(s);
  344.     
  345.     return 0;
  346. }
  347.  
  348. /////////////////////////////////////////////////////////////////////////////
  349.  
  350.